import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:card_swiper/card_swiper.dart';
import 'package:dotted_line/dotted_line.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_rtk/api/api.dart';
import 'package:flutter_rtk/common/assets.dart';
import 'package:flutter_rtk/common/common.dart';
import 'package:flutter_rtk/common/config.dart';
import 'package:flutter_rtk/common/constants.dart';
import 'package:flutter_rtk/entities/banner_entity.dart';
import 'package:flutter_rtk/entities/collection_tools_page_entity.dart';
import 'package:flutter_rtk/entities/current_project_entity.dart';
import 'package:flutter_rtk/entities/message_page_entity.dart';
import 'package:flutter_rtk/entities/project_entity.dart';
import 'package:flutter_rtk/entities/sync_business_entity.dart';
import 'package:flutter_rtk/entities/tools_entity.dart';
import 'package:flutter_rtk/entities/undo_page_entity.dart';
import 'package:flutter_rtk/entities/user_entity.dart';
import 'package:flutter_rtk/models/app_model.dart';
import 'package:flutter_rtk/models/user_info_model.dart';
import 'package:flutter_rtk/router/index.dart';
import 'package:flutter_rtk/service/connectivity_service.dart';
import 'package:flutter_rtk/service/database_service.dart';
import 'package:flutter_rtk/service/store_service.dart';
import 'package:flutter_rtk/utils/h5_download_utils.dart';
import 'package:flutter_rtk/utils/md5_utils.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_upgrader/flutter_upgrader_manager.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
  final RefreshController refreshController = RefreshController();
  final todoIcons = [
    Image.asset(AppAssets.homeTodo01),
    Image.asset(AppAssets.homeTodo02),
    Image.asset(AppAssets.homeTodo03),
  ];

  // 常用工具
  List<ToolsEntity> commonMenus = [];

  _buildMainView() {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: mainAppBar(title: "数字建造平台", rightButton: _buildSwitchProjectBtn()),
      body: SmartRefresher(
        controller: refreshController,
        header: WaterDropHeader(
          complete: Text("刷新成功", style: TextStyle(fontSize: 28.sp, color: AppConstants.brandColor, fontWeight: FontWeight.normal)),
          waterDropColor: AppConstants.brandColor,
        ),
        onRefresh: () {
          if (!ConnectivityService.to.isOnline) {
            showToast("离线状态无法刷新, 请联网后重试");
            refreshController.refreshFailed();
            return;
          }
          _initData(isRefresh: true).then((v) {
            refreshController.refreshCompleted();
          }).catchError((e) {
            refreshController.refreshFailed();
          });
        },
        child: CustomScrollView(slivers: [
          // 项目
          _buildProjectSwiper(),
          // 消息
          _buildScrollMessage(),
          // 常用工具
          _buildCommonOperation(),
          // 待办
          _buildToDoList(),
        ]),
      ),
    );
  }

  ///
  _buildToDoList() {
    // int count = 4;
    double offset = 40;
    return Consumer<AppModel>(builder: (context, app, child) {
      if (app.undoTaskInfo == null) {
        return SliverToBoxAdapter(child: SizedBox(width: double.infinity, height: 100.h));
      }
      return SliverToBoxAdapter(
        child: SizedBox(
          width: double.infinity,
          height: (63 + (app.undoTaskInfo!.records.length * 80) + offset).h,
          child: Column(children: [
            // 43.h
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 25.w),
              child: _buildHeader(
                title: "待办",
                suffixWidget: Padding(
                  padding: EdgeInsets.only(right: 10.w),
                  child: InkWell(
                    onTap: () => Navigator.pushNamed(context, AppRouters.toMyTodoPage),
                    child: Text("更多", style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600, color: const Color(0xFFB9C4D8))),
                  ),
                ),
              ),
            ),
            SizedBox(height: 20.h),
            app.undoTaskInfo!.records.isNotEmpty
                ? Container(
                    width: double.infinity,
                    height: (app.undoTaskInfo!.records.length * 80).h,
                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(10.r), boxShadow: const [BoxShadow(color: Color(0xFFDEEFFF), blurRadius: 20)]),
                    alignment: Alignment.center,
                    child: Container(
                      width: 700.w,
                      height: double.infinity,
                      color: Colors.white,
                      child: ListView.builder(
                        physics: const NeverScrollableScrollPhysics(),
                        itemBuilder: (BuildContext context, int index) {
                          return _buildTodoItem(isLast: index == app.undoTaskInfo!.records.length - 1, undoInfo: app.undoTaskInfo!.records[index], idx: index % 3);
                        },
                        itemCount: app.undoTaskInfo!.records.length,
                      ),
                    ),
                  )
                : Expanded(child: Container(width: double.infinity, height: double.infinity, alignment: Alignment.center, child: const Text("暂无待办信息"))),
          ]),
        ),
      );
    });
  }

  _buildTodoItem({bool isLast = false, required UndoItem undoInfo, required int idx}) {
    return InkWell(
      onTap: () {
        // {id: 1686716099648671746, businessCode: , title: 周报测试流程, projectName: , sourceName: 安环周报, sourceCode: SEP, startUserId: 1668176854726291457, startUserName: 高强权1,
        // endUserId: -1, endUserName: , startDate: 2023-08-02 20:30:30, endDate: , thirdInsId: 645d700e-3125-11ee-9a58-fa163e97a367, insSuccess: false, insId: 1686696326953029634,
        // sendUserId: 1668176854726291457, sendUserName: 高强权1, sendDate: 2023-08-02 20:30:30, receiverId: 1668176854726291457, approverId: -1, approverName: , approveStatus: ,
        // approveTime: 2023-08-02 20:30:30, costTime: , targetUrl: /workflow/#/process/external/iframe/detail, targetMobileUrl: /workflow/#/process/external/iframe/detail, success: false,
        // thirdTaskId: 5e355a30-3130-11ee-9a58-fa163e97a367, remark: , operationName: 填报}
        if (undoInfo.sourceCode == "SEP" || undoInfo.sourceCode == "CIP") {
          String token = StoreService.to.getString(AppConstants.token);
          if (token.startsWith("bearer ")) {
            token = token.substring(7);
          }
          String url = "${AppConfig.homeTodoCIPPrefixDomain}?token=$token&url=${Uri.encodeComponent(undoInfo.targetMobileUrl.replaceAll("&amp;", "&"))}&type=workflow&sourceCode=${undoInfo.sourceCode}&thirdInsId=${undoInfo.thirdInsId}&thirdTaskId=${undoInfo.thirdTaskId}&showAppbar=1";
          Navigator.pushNamed(context, AppRouters.webview, arguments: {"title": undoInfo.title, "url": url});
        } else if (undoInfo.sourceCode == "EPC") {
          String token = StoreService.to.getString(AppConstants.token);
          if (token.startsWith("bearer ")) {
            token = token.substring(7);
          }
          String url = "${AppConfig.homeTodoEPCPrefixDomain}?Sinoma_Auth=$token&redirect=${Uri.encodeComponent(undoInfo.targetMobileUrl.replaceAll("&amp;", "&"))}&showAppbar=1";
          Navigator.pushNamed(context, AppRouters.webview, arguments: {"title": undoInfo.title, "url": url.replaceAll("&amp", "")});
        } else {
          showToast("功能未开放,请联系管理员");
        }
      },
      child: Container(
        width: double.infinity,
        height: 80.h,
        padding: EdgeInsets.only(left: 45.w, right: 25.w),
        child: Column(children: [
          Expanded(
            child: Row(children: [
              SizedBox(width: 32.w, height: 32.h, child: todoIcons[idx]),
              SizedBox(width: 20.w),
              Expanded(child: Text(undoInfo.title, style: TextStyle(fontSize: 28.sp, fontWeight: FontWeight.w500, color: const Color(0xFF666666)), overflow: TextOverflow.ellipsis, maxLines: 1)),
            ]),
          ),
          !isLast ? const DottedLine(dashColor: Color(0xFFC8C8C8)) : const SizedBox.shrink(),
        ]),
      ),
    );
  }

  /// width: 700.w height: 80.h + 2 * 20.h
  _buildScrollMessage() {
    return SliverToBoxAdapter(
      child: Container(
        width: double.infinity,
        height: 80.h,
        margin: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.h),
        decoration: BoxDecoration(color: const Color(0xFFF4F4F4), borderRadius: BorderRadius.circular(12.r)),
        child: Padding(
          padding: EdgeInsets.only(left: 20.w, right: 20.w),
          child: Row(children: [
            Expanded(
              child: Row(children: [
                SizedBox(width: 80.w, height: 40.h, child: Image.asset(AppAssets.homeMessage)),
                VerticalDivider(color: const Color(0xFFD8D8D8), indent: 30.h, endIndent: 25.h, width: 15.w),
                Consumer<AppModel>(builder: (context, app, child) {
                  if (app.unReadMessagePage == null || app.unReadMessagePage!.records.isEmpty) {
                    return Text("暂无未读消息", style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.normal, color: const Color(0xFF444444)), maxLines: 1, overflow: TextOverflow.ellipsis);
                  }
                  return Expanded(
                    child: Swiper(
                      scrollDirection: Axis.vertical,
                      itemCount: app.unReadMessagePage!.records.length,
                      autoplay: true,
                      loop: true,
                      itemBuilder: (context, idx) {
                        var v = app.unReadMessagePage!.records[idx];
                        return InkWell(
                          onTap: () => Navigator.pushNamed(context, AppRouters.toMessageDetailPage, arguments: {"messageId": v.msgId, "title": v.msgTile}),
                          child: Container(
                            padding: EdgeInsets.only(right: 8.w),
                            alignment: Alignment.centerLeft,
                            child: Text("${v.msgTile}:${v.msgContent}", style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.normal, color: const Color(0xFF444444)), maxLines: 1, overflow: TextOverflow.ellipsis),
                          ),
                        );
                      },
                    ),
                  );
                })
              ]),
            ),
            // SizedBox(width: 54.w, height: 28.h, child: ),
            InkWell(
              onTap: () {
                if (ConnectivityService.to.isOnline) {
                  Navigator.pushNamed(context, AppRouters.toMessagePage);
                  return;
                }
                showToast("离线状态无法获取更多消息");
              },
              child: FittedBox(child: Text("更多", style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.normal, color: const Color(0xFF999999)))),
            ),
          ]),
        ),
      ),
    );
  }

  // height: 323.h, width: double.infinity,
  _buildProjectSwiper() {
    return SliverToBoxAdapter(
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 20.w),
        child: Column(children: [
          // 43.h
          Consumer<AppModel>(builder: (context, app, child) {
            if (app.currentProjectInfo == null) {
              return _buildProjectHeader(title: "--");
            }
            return _buildProjectHeader(title: app.currentProjectInfo!.mergeName);
          }),
          SizedBox(height: 8.h),
          Container(
            width: double.infinity,
            height: 280.h,
            clipBehavior: Clip.antiAlias,
            decoration: BoxDecoration(borderRadius: BorderRadius.circular(12.r)),
            child: Consumer<AppModel>(
              builder: (context, app, child) {
                if (app.bannerEntity == null) {
                  return Container(width: double.infinity, height: double.infinity, color: Colors.grey.shade50, alignment: Alignment.center, child: const Text("Loading..."));
                }
                if (app.bannerEntity!.records.isEmpty) {
                  return SizedBox(width: double.infinity, height: double.infinity, child: Image.asset(AppAssets.defaultBanner, fit: BoxFit.fill));
                }
                return Swiper(
                  itemBuilder: (BuildContext context, int index) => CachedNetworkImage(imageUrl: app.bannerEntity!.records[index].filePath, fit: BoxFit.fill),
                  itemCount: app.bannerEntity!.records.length,
                  pagination: const SwiperPagination(builder: DotSwiperPaginationBuilder(size: 8, activeSize: 8, activeColor: Color(0xFF3235BE))),
                );
              },
            ),
          ),
        ]),
      ),
    );
  }

  // height: 220.h, width: double.infinity,
  _buildCommonOperation() {
    return SliverToBoxAdapter(
      child: Consumer<AppModel>(builder: (context, app, child) {
        commonMenus = [];
        commonMenus.addAll(app.collectionTools);
        // 添加自定义按钮
        commonMenus.add(ToolsEntity("", "0", "", "更多工具", "--", "更多工具" "", "0", -1, -1, -1, -1, -1, "", -1, "更多工具", "", -1, "", "", -1, "", "", [], false, "", "", "", ""));
        // 然后计算行数
        int rows = (commonMenus.length + 3) ~/ 4;
        return Container(
          color: Colors.white,
          padding: EdgeInsets.symmetric(horizontal: 20.w),
          child: Container(
            width: double.infinity,
            height: (94 + (156 * rows)).h,
            margin: EdgeInsets.only(top: 20.h),
            child: Column(children: [
              _buildHeader(title: "常用操作"),
              SizedBox(height: 30.h),
              SizedBox(
                width: double.infinity,
                height: (156 * rows).h,
                child: ListView.builder(
                  physics: const NeverScrollableScrollPhysics(),
                  itemBuilder: (context, rowIdx) {
                    int endIdx = rowIdx * 4 + 4 < commonMenus.length ? rowIdx * 4 + 4 : commonMenus.length;
                    List<ToolsEntity> partCollectionMenus = commonMenus.sublist(rowIdx * 4, endIdx);
                    int length = partCollectionMenus.length;
                    return Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
                      Flexible(child: _buildRowItemButton(length > 0 ? partCollectionMenus[0] : null)),
                      Flexible(child: _buildRowItemButton(length > 1 ? partCollectionMenus[1] : null)),
                      Flexible(child: _buildRowItemButton(length > 2 ? partCollectionMenus[2] : null)),
                      Flexible(child: _buildRowItemButton(length > 3 ? partCollectionMenus[3] : null)),
                    ]);
                  },
                  itemCount: rows,
                ),
              ),
            ]),
          ),
        );
      }),
    );
  }

  _buildRowItemButton(ToolsEntity? menu) {
    if (menu == null) {
      return SizedBox(width: 156.w, height: 156.h);
    }
    return SizedBox(
      width: 156.w,
      height: 156.h,
      child: InkWell(
        onTap: () {
          if (menu.id.isEmpty) {
            context.read<AppModel>().changeCurrentIdx(1, isEdit: true);
          } else {
            if (menu.path.isNotEmpty) {
              try {
                jsonDecode(menu.path);
              } catch (e) {
                //
                if (menu.path.startsWith("/")) {
                  Navigator.pushNamed(context, AppRouters.webview, arguments: {"title": menu.name, "url": menu.path});
                  return;
                }
              }
              Map path = jsonDecode(menu.path);
              if (path['Type'] == "H5") {
                Navigator.pushNamed(context, AppRouters.webview, arguments: {"title": menu.name, "url": path['Url']});
              } else {
                showToast("功能暂无法使用,请联系工作人员");
              }
            } else {
              showToast("功能暂未开放, 敬请期待");
            }
          }
        },
        child: SizedBox(
          width: double.infinity,
          height: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              SizedBox(
                  width: 85.h,
                  height: 85.h,
                  child: menu.id.isEmpty
                      ? Image.asset(AppAssets.moreTools)
                      : ConnectivityService.to.isOnline
                          ? CachedNetworkImage(imageUrl: menu.filePath)
                          : Image.asset(AppAssets.offlineIcon)),
              SizedBox(height: 15.h),
              FittedBox(child: Text(menu.name, style: TextStyle(fontSize: 24.sp, color: const Color(0xFF333333), fontWeight: FontWeight.normal))),
            ],
          ),
        ),
      ),
    );
  }

  _buildHeader({required String title, String? subTitle, Widget? suffixWidget}) {
    return SizedBox(
      width: double.infinity,
      height: 43.h,
      child: Row(children: [
        Text(title, style: TextStyle(fontSize: 30.sp, color: const Color(0xFF121212), fontWeight: FontWeight.w600)),
        subTitle != null ? Text(subTitle, style: TextStyle(fontSize: 24.sp, color: const Color(0xFF999999))) : const SizedBox.shrink(),
        const Spacer(),
        // ignore: prefer_if_null_operators
        suffixWidget != null ? suffixWidget : const SizedBox.shrink(),
      ]),
    );
  }

  _buildProjectHeader({required String title, String? subTitle, Widget? suffixWidget}) {
    return SizedBox(
      width: double.infinity,
      height: 43.h,
      child: Row(children: [
        Container(width: 12.w, height: 25.h, decoration: BoxDecoration(color: const Color(0xFF156FFE), borderRadius: BorderRadius.circular(30.r))),
        SizedBox(width: 15.w),
        Expanded(child: Text(title, style: TextStyle(fontSize: 30.sp, color: const Color(0xFF121212), fontWeight: FontWeight.w400), overflow: TextOverflow.ellipsis)),
        subTitle != null ? Text(subTitle, style: TextStyle(fontSize: 24.sp, color: const Color(0xFF999999))) : const SizedBox.shrink(),
        // ignore: prefer_if_null_operators
        suffixWidget != null ? suffixWidget : const SizedBox.shrink(),
      ]),
    );
  }

  _buildSwitchProjectBtn() {
    return TextButton(
      onPressed: () => Navigator.pushNamed(context, AppRouters.toSwitchProjectPage),
      style: ButtonStyle(overlayColor: MaterialStateProperty.resolveWith((states) => Colors.transparent)),
      child: Text("项目切换", style: TextStyle(fontSize: 28.sp, fontWeight: FontWeight.w600, color: const Color(0xFF007AFF))),
    );
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return _buildMainView();
  }

  @override
  void initState() {
    super.initState();
    if (ConnectivityService.to.isOnline) {
      // 数据初始化
      _initData();
      // 同步配置(必须在升级之前,防止升级后清空本地数据)
      _syncBusinessToServer();
      // 联网检测版本升级信息
      _upgradeApplication();
      // 同步配置
      _syncSettingsFromServer();
    } else {
      _initData(isOnline: false);
    }
  }

  _syncSettingsFromServer() async {
    // 获取服务端配置接口, 更新本地配置表数据
    List<dynamic> configs = await AppApi.fetchConfigList();
    if (configs.isEmpty) {
      return;
    }
    // 循环接口调用获取配置数据
    // 根据版本号判断是否需要调用接口更新基础数据(需要版本号字段)
    // {id: 9, dataType: 2, requestUrl: https://cip.sinoma-ncdri.cn/, dataTable: 11, dataColumn: 11, sqlScript: 11, createTime: 2023-09-27 16:33:26,
    // createUser: 1668176854726291457, updateTime: 2023-09-27 16:33:26, updateUser: 1668176854726291457, isDeleted: 0}
    for (var item in configs) {
      // 如果表存在 && 版本号没有变更则不更新
      bool isExist = await DatabaseService.to.existTable(tableName: item['dataTable']);
      if (isExist) {
        continue;
      }
      print(item);
      // String configId = MD5Utils.toMD5(item['dataTable']);
      try {
        // 生成新表
        await DatabaseService.to.createNewTable(item['sqlScript']);
        // 请求url，获取数据，写入新表
        List<dynamic> dataList = await AppApi.invokeUrl(url: item['requestUrl'], timeout: 30000);
        if (dataList.isEmpty) {
          continue;
        }
        await DatabaseService.to.batchInsert(tableName: item['dataTable'], columns: item['dataColumn'], dataList: dataList);
      } catch (e) {
        // 删除表
        await DatabaseService.to.deleteTable(tableName: item['dataTable']);
        debugPrintStack(label: "$e");
      }
    }
  }

  _syncBusinessToServer() async {
    bool existBusinessTable = await DatabaseService.to.existTable();
    if (!existBusinessTable) {
      return;
    }
    // 查询所有未同步数据, 同步给服务端
    List<SyncBusinessEntity> results = await DatabaseService.to.findBusinessSync(where: "is_synchronized = ?", whereArgs: [0]);
    if (results.isNotEmpty) {
      Map<String, dynamic> businessMap = {for (var item in results) item.business: results.where((element) => element.business == item.business).toList()};
      Iterable<String> keys = businessMap.keys;
      if (keys.isEmpty) {
        return;
      }
      List<Map<String, dynamic>> data = [];
      for (var k in keys) {
        List<Map<String, dynamic>> newData = [];
        List<SyncBusinessEntity> entities = businessMap[k];
        try {
          for (SyncBusinessEntity s in entities) {
            // 循环解析图片。如果有则上传图片，然后写入
            newData.add(await _uploadImageAndUpdate(s));
          }
        } catch (e) {
          // 本次不同步
          debugPrintStack(label: "$e");
          continue;
        }
        data.add({
          "businessKey": k,
          "businessVal": newData,
        });
      }
      if (data.isEmpty) {
        return;
      }
      try {
        await AppApi.syncOfflineData(data: data);
        await DatabaseService.to.batchUpdateBusinessSync();
      } catch (e) {
        debugPrintStack(label: "$e");
      }
    }
  }

  _uploadImageAndUpdate(SyncBusinessEntity s) async {
    // 固定格式解析图片，然后上传，然后组装新数据写入表中
    if (s.images.isEmpty) {
      // 没有图片不需要上传
      return Future(() {
        Map<String, dynamic> item = s.toJson();
        item["imgs"] = [];
        item.remove("images");
        return item;
      });
    }
    // / [
    // /   {
    // /     "biz":"aaa",
    // /     "imgpath":"s.jpg"
    // /   }
    // / ]
    List<dynamic> images = jsonDecode(s.images);
    if (images.isEmpty) {
      return Future(() {
        Map<String, dynamic> item = s.toJson();
        item["imgs"] = [];
        item.remove("images");
        return item;
      });
    }
    List<Map<String, dynamic>> newImages = [];
    for (var img in images) {
      String? path = img['imgpath'];
      if (path != null && !(path.startsWith("http://") || path.startsWith("https://"))) {
        List<String> newPaths = [];
        var arr = path.split(",");
        for (var p in arr) {
          var res = await AppApi.uploadFile(path: p);
          if (res['code'] == 200) {
            newPaths.add(res['data']['link']);
          } else {
            throw Exception(res['message']);
          }
        }
        if (newPaths.isNotEmpty) {
          img['imgpath'] = newPaths.join(",");
        }
      }
      newImages.add(img);
    }
    // 更新图片数据
    s.images = jsonEncode(newImages);
    // 更新表
    await DatabaseService.to.updateBusinessSync(s.id, null, s.images);
    return Future(() {
      Map<String, dynamic> item = s.toJson();
      item["imgs"] = newImages;
      item.remove("images");
      return item;
    });
  }

  _upgradeApplication() async {
    // PackageInfo(appName: 数字建造平台, buildNumber: 1, packageName: com.rtk.flutter_rtk, version: 1.2.0, buildSignature: B24A8AA42B7D01C2B7694CE8AA6B08413BA25750, installerStore: null)
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    // 检测更新
    AppApi.fetchLatestOfflinePackage(packageType: 1, platformType: Platform.isAndroid ? "1" : "2").then((res) {
      int version = int.parse(res.versonNumber);
      String path = res.packagePath;
      String remark = res.applyType.isNotEmpty ? res.applyType : '有新版本哟,请更新～';
      var updateContent = remark.split(";");
      // int fileSize = remark['fileSize'] as int;
      int currentVersion = int.parse(packageInfo.version.replaceAll(".", ""));
      if (version > currentVersion) {
        Map<String, String> headers = {
          "Authorization": "Basic ${base64.encode("${AppConfig.clientId}:${AppConfig.clientSecret}".codeUnits)}",
          "Tenant-Id": AppConfig.defaultTenantId,
          "Sinoma-Auth": StoreService.to.getString(AppConstants.token),
        };
        final appUpgradeInfo = Future(() => AppUpgradeInfo(title: '更新提示', contents: updateContent, apkDownloadUrl: path, force: false, headers: headers));
        // IOS这里的iosAppId需要替换
        AppUpgradeManager.upgrade(context, appUpgradeInfo, iosAppId: 'xxxxxx');
      }
    });
    return;
  }

  // late CurrentProjectEntity _offlineCurrentProjectEntity;

  Future<bool> _initData({bool isRefresh = false, bool isOnline = true}) async {
    if (isOnline) {
      EasyLoading.showProgress(0, status: "初始化中...");
      // 获取用户信息
      _fetchUserInfo((user) async {
        context.read<UserInfoModel>().setUserInfo(user);
        // 更新用户信息； 离线使用
        List<Map<String, Object?>> users = await DatabaseService.to.find(tableName: "t_user", where: "id = ?", whereArgs: [1]);
        if (users.isEmpty) {
          return;
        }
        Map<String, Object?> dbUser = Map.from(users[0]);
        // 写入用户信息
        dbUser["user_info"] = jsonEncode(user.toJson());
        // 更新用户信息
        await DatabaseService.to.update(tableName: "t_user", id: 1, data: dbUser);
      });
      EasyLoading.showProgress(0, status: "初始化中...");
      // 获取banner数据
      await _fetchBannerInfo((banners) => context.read<AppModel>().setBannerInfo(banners));
      EasyLoading.showProgress(0.2, status: "初始化中...");
      // 获取所有项目数据、当前项目、所有菜单数据、所有未读消息数据
      await _fetchAllProjects(isRefresh, (projects, currentProject, collectionTools, messagePageInfo) async {
        if (isRefresh) {
          context.read<AppModel>().setCollectionTools(collectionTools);
          context.read<AppModel>().setUnreadMessageInfo(messagePageInfo);
        } else {
          // 所有项目和当前已选择项目不参与下拉刷新操作
          context.read<AppModel>().setAllProjects(projects);
          context.read<AppModel>().setCurrentProject(currentProject);
          context.read<AppModel>().setCollectionTools(collectionTools);
          context.read<AppModel>().setUnreadMessageInfo(messagePageInfo);
        }
        // 更新项目信息，离线使用
        DatabaseService.to.clear(tableName: "t_project").then((v) {
          DatabaseService.to.batchInsertProject(projects, currentProject.projectId);
        });
      });
      EasyLoading.showProgress(0.6, status: "初始化中...");
      await _fetchAllUndoTasks((undoTask) => context.read<AppModel>().setUndoTaskInfo(undoTask));
      EasyLoading.showProgress(0.7, status: "初始化中...");
      // 下载RTK离线H5包，离线使用
      await H5DownloadUtils.downloadH5(business: "RTK", applyType: "基坑");
      EasyLoading.showSuccess("初始化完成");
    } else {
      List<Map<String, Object?>> projects = await DatabaseService.to.find(tableName: "t_project");
      if (projects.isNotEmpty) {
        // 递归组装项目
        List<ProjectEntity> allProjects = _recursionFillProject(root: "0", data: projects);
        // ignore: use_build_context_synchronously
        context.read<AppModel>().setAllProjects(allProjects);
        var directory = await getApplicationDocumentsDirectory();
        List<Map<String, Object?>> currentProjects = await DatabaseService.to.find(tableName: "t_project", where: "is_current = ?", whereArgs: [1]);
        Map<String, Object?> current = currentProjects[0];
        var entity = ProjectEntity("${current['project_name']}", "${current['project_code']}", "${current['project_id']}", "${current['dept_code']}", "${current['dept_name']}", "{${current['project_type']}", "${current['parent_id']}", [], [], "${current['merge_name']}");
        CurrentProjectEntity offlineCurrentProjectEntity = CurrentProjectEntity(entity.projectId, "--", entity.deptName, "--", "--", "--", 0, 0, "", entity.projectCode, entity.projectId, entity.deptCode, "", entity.mergeName);
        // ignore: use_build_context_synchronously
        context.read<AppModel>().setCurrentProject(offlineCurrentProjectEntity);
        // 离线, 菜单信息也从表中获取; 目前只有RTK先写死
        var rtk = CollectionToolsItem(
            "1", "createUser", "createDept", "createTime", "updateUser", "updateTime", 0, 0, "", 0, "menuId", "menuSource", "RTK", "RTK", 0, "userId", "filePath", "${directory.path}/html/RTK/index.html?isLocal=1", offlineCurrentProjectEntity.projectId, offlineCurrentProjectEntity.projectCode);
        // ignore: use_build_context_synchronously
        context.read<AppModel>().setCollectionTools(CollectionToolsPageEntity([rtk], 1, 1, 1, [], true, true, "", 10, 1));
      } else {
        showToast("暂无离线数据，请检查当前网络！");
      }
      List<Map<String, Object?>> users = await DatabaseService.to.find(tableName: "t_user", where: "id = ?", whereArgs: [1]);
      if (users.isNotEmpty) {
        Map<String, dynamic> dbUser = users[0];
        // ignore: use_build_context_synchronously
        context.read<UserInfoModel>().setUserInfo(UserEntity.fromJson(jsonDecode(dbUser['user_info'])));
      }
      // 默认banner信息, 消息和待办都为空
      // ignore: use_build_context_synchronously
      context.read<AppModel>().setBannerInfo(BannerEntity([], 0, 0, 0, [], false, false, "", 0, 0));
      // ignore: use_build_context_synchronously
      context.read<AppModel>().setUnreadMessageInfo(null);
      // ignore: use_build_context_synchronously
      context.read<AppModel>().setUndoTaskInfo(null);
    }
    return Future(() => true);
  }

  List<ProjectEntity> _recursionFillProject({required String root, required List<Map<String, Object?>> data}) {
    List<ProjectEntity> results = [];
    if (data.isNotEmpty) {
      for (var item in data) {
        var entity = ProjectEntity("${item['project_name']}", "${item['project_code']}", "${item['project_id']}", "${item['dept_code']}", "${item['dept_name']}", "{${item['project_type']}", "${item['parent_id']}", [], [], "${item['merge_name']}");
        if (entity.parentId == root) {
          entity.child = entity.children = _recursionFillProject(root: entity.projectId, data: data);
          // if (item["is_current"] == 1) {
          //   print(item);
          //   // 是否当前项目
          //   _offlineCurrentProjectEntity = CurrentProjectEntity(entity.projectId, "--", entity.deptName, "--", "--", "--", 0, 0, "", entity.projectCode, entity.projectId, entity.deptCode, "", entity.mergeName);
          // }
          results.add(entity);
        }
      }
    }
    return results;
  }

  _fetchUserInfo(Function(UserEntity user) callback) async {
    try {
      UserEntity user = await AppApi.getUserInfo();
      callback(user);
    } catch (e, stack) {
      debugPrintStack(stackTrace: stack, label: "$e");
      showToast("获取用户信息失败");
      rethrow;
    }
  }

  _fetchBannerInfo(Function(BannerEntity banner) callback) async {
    try {
      BannerEntity bannerEntity = await AppApi.getSwiperInfo();
      callback(bannerEntity);
    } catch (e, stack) {
      debugPrintStack(stackTrace: stack, label: "$e");
      showToast("获取轮播信息失败");
      rethrow;
    }
  }

  _fetchAllProjects(bool isRefresh, Function(List<ProjectEntity> projects, CurrentProjectEntity currentProjectEntity, CollectionToolsPageEntity collectionTools, MessagePageEntity messagePageInfo) callback) async {
    try {
      if (isRefresh) {
        var currentProject = context.read<AppModel>().currentProjectInfo;
        if (currentProject != null) {
          // 获取常用工具
          CollectionToolsPageEntity collectionToolsPageEntity = await AppApi.getCommonTools(projectId: currentProject.projectId, projectCode: currentProject.projectCode);
          // 获取未读消息
          MessagePageEntity messagePageInfo = await AppApi.getMessagePage(isRead: 1);
          // ignore: use_build_context_synchronously
          callback(context.read<AppModel>().projects, currentProject, collectionToolsPageEntity, messagePageInfo);
        }
      } else {
        // 获取所有项目
        List<ProjectEntity> projects = await AppApi.getAllProjects();
        // 获取当前项目
        CurrentProjectEntity? currentProject = await AppApi.getCurrentProject();
        // 如果当前项目未匹配到,则取第一个作为该项目
        if (currentProject == null) {
          ProjectEntity first = projects.first;
          if (first.children.isNotEmpty) {
            first = ProjectEntity.fromJson(first.children[0]);
          }
          currentProject = CurrentProjectEntity(first.projectId, "--", first.deptName, "--", "--", "--", 0, 0, "", first.projectCode, first.projectId, first.deptCode, "", first.mergeName);
        } else {
          if (!projects.any((element) => element.mergeName == currentProject!.mergeName)) {
            ProjectEntity first = projects.first;
            if (first.children.isNotEmpty) {
              first = ProjectEntity.fromJson(first.children[0]);
            }
            currentProject = CurrentProjectEntity(first.projectId, "--", first.deptName, "--", "--", "--", 0, 0, "", first.projectCode, first.projectId, first.deptCode, "", first.mergeName);
          }
        }
        // 获取常用工具
        CollectionToolsPageEntity collectionToolsPageEntity = await AppApi.getCommonTools(projectId: currentProject.projectId, projectCode: currentProject.projectCode);
        // 获取未读消息
        MessagePageEntity messagePageInfo = await AppApi.getMessagePage(isRead: 1);
        callback(projects, currentProject, collectionToolsPageEntity, messagePageInfo);
      }
    } catch (e, stack) {
      debugPrintStack(stackTrace: stack, label: "$e");
      showToast("获取项目信息失败");
      rethrow;
    }
  }

  _fetchAllUndoTasks(Function(UndoPageEntity undoTaskEntity) callback) async {
    try {
      UndoPageEntity undoTaskEntity = await AppApi.getUndoPage(action: "undo");
      callback(undoTaskEntity);
    } catch (e, stack) {
      debugPrintStack(stackTrace: stack, label: "$e");
      showToast("获取所有待办任务失败");
      rethrow;
    }
  }

  @override
  bool get wantKeepAlive => true;
}
